package com.sparrow.rpc.manager;

import com.sparrow.common.util.PropertiesUtil;
import com.sparrow.rpc.domain.RpcNode;
import com.sparrow.rpc.socket.RpcClient;
import com.sparrow.rpc.socket.listenner.GameCenterNodeConnectListener;
import com.sparrow.rpc.socket.msg.req.RpcLoginRequest;
import com.sparrow.rpc.socket.msg.resp.RpcLoginResponse;
import com.sparrow.rpc.socket.msg.resp.RpcNodeBroadcastResponse;
import com.sparrow.rpc.socket.msg.vo.RpcNodeVo;
import com.sparrow.rpc.socket.session.RpcClientSessionManager;
import com.sparrow.rpc.socket.session.RpcServerSessionManager;
import com.sparrow.rpc.socket.session.RpcSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.stream.Collectors;

/**
 * CS架构 游戏服->中心服 架构 的rpc节点实现
 * NodeManager 类负责管理节点的注册、查找和注销操作。
 */
public class GameRpcNodeManager extends AbsRpcNodeManager implements ApplicationListener<ContextRefreshedEvent> {

    private static final Logger logger = LoggerFactory.getLogger(GameRpcNodeManager.class);
    /**
     * 中心节点
     */
    private RpcNode center;

    @Autowired
    RpcServerSessionManager serverSessionManager;

    @Autowired
    RpcClientManager clientManager;

    private static GameRpcNodeManager INSTANCE;
    public static GameRpcNodeManager getInstance() {
        return INSTANCE;
    }

    public GameRpcNodeManager() {
        INSTANCE = this;
    }

    @PostConstruct
    private void init() {
        //注册自己
        self = registerNode(PropertiesUtil.getProperty("rpc.node.id"), PropertiesUtil.getProperty("rpc.node.ip"), PropertiesUtil.getPropertyAsInt("rpc.node.port"));
        //注册中心节点
        center = registerNode(PropertiesUtil.getProperty("rpc.node.center.id"), PropertiesUtil.getProperty("rpc.node.center.ip"), PropertiesUtil.getPropertyAsInt("rpc.node.center.port"));
    }


    public RpcNode getCenter() {
        return center;
    }

    /**
     * 主方法，用于测试 NodeManager 类的功能。
     */
    public boolean isCenter() {
        return self.equals(center);
    }

    public void onRpcNodeLogin(RpcSession session, RpcLoginRequest nodeRequest) {
        if (isCenter()) { //中心服充当服务发现
            broadcastNodeInfo(nodeRequest.getNodeId());
        }
    }

    @Override
    public void onRpcNodeLoginResp(RpcSession session, RpcLoginResponse response) {
        if (response.getTargetNodeId().equals(getCenter().getId())) {
            logger.info("rpc登录中心节点返回 centerNodeId:{} loginNodeId:{}", response.getTargetNodeId(), response.getLoginNodeId());
        }
    }

    private void broadcastNodeInfo(String loginNodeId) {
        RpcNodeBroadcastResponse response = new RpcNodeBroadcastResponse();
        response.setTargetNodeId(getSelf().getId());
        response.setLoginNodeId(loginNodeId);
        response.setNodeList(nodeMap.values().stream().map(e -> RpcNodeVo.of(e)).collect(Collectors.toList()));
        //中心服只会接收连接 所有用serverSessionMgr
        Collection<RpcSession> allSession = serverSessionManager.getAllSession();
        for (RpcSession session : allSession) {
            session.writeAndFlush(response);
        }
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        RpcNode self = getSelf();
        //不是注册中心节点的话会自动连接注册
        RpcNode center = getCenter();
        if (!isCenter()) {
            RpcClient rpcClient = clientManager.getRpcClient(center.getId());
            rpcClient.connect(new GameCenterNodeConnectListener(self));
        }
    }
}